home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / DRAWPIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-01  |  29.8 KB  |  989 lines

  1. /* $Id: drawpix.c,v 3.14 1998/08/01 04:52:47 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: drawpix.c,v $
  26.  * Revision 3.14  1998/08/01 04:52:47  brianp
  27.  * fixed conformance problems in GL_DEPTH_COMPONENT and GL_STENCIL_INDEX code
  28.  *
  29.  * Revision 3.13  1998/07/17 03:24:16  brianp
  30.  * added Pixel.ScaleOrBiasRGBA field
  31.  *
  32.  * Revision 3.12  1998/06/28 22:32:22  brianp
  33.  * fixed Mac compilation problem (Randy Frank and Miklos Fazekas)
  34.  *
  35.  * Revision 3.11  1998/06/01 00:38:13  brianp
  36.  * fixed off-by-one bug in glDrawPixels clipping (Randy Frank)
  37.  *
  38.  * Revision 3.10  1998/05/31 23:50:36  brianp
  39.  * cleaned up a few Solaris compiler warnings
  40.  *
  41.  * Revision 3.9  1998/04/01 02:58:52  brianp
  42.  * applied Miklos Fazekas's 3-31-98 Macintosh changes
  43.  *
  44.  * Revision 3.8  1998/03/27 03:39:14  brianp
  45.  * fixed G++ warnings
  46.  *
  47.  * Revision 3.7  1998/03/26 03:09:09  brianp
  48.  * added GL_LUMINANCE and GL_LUMINANCE_ALPHA to gl_direct_DrawPixels()
  49.  *
  50.  * Revision 3.6  1998/03/25 01:56:03  brianp
  51.  * fixed bug when Zoom.Y != 1.0 and top/bottom clipping needed (Randy Frank)
  52.  *
  53.  * Revision 3.5  1998/03/22 16:42:30  brianp
  54.  * added CI->RGBA conversion to gl_direct_DrawPixels()
  55.  *
  56.  * Revision 3.4  1998/03/10 01:28:22  brianp
  57.  * moved a few DEFARRY macros
  58.  *
  59.  * Revision 3.3  1998/02/08 20:22:14  brianp
  60.  * LOTS of clean-up and rewriting
  61.  *
  62.  * Revision 3.2  1998/02/04 00:33:45  brianp
  63.  * fixed a few cast problems for Amiga StormC compiler
  64.  *
  65.  * Revision 3.1  1998/02/01 22:16:34  brianp
  66.  * include different headers (zooming)
  67.  *
  68.  * Revision 3.0  1998/01/31 20:51:03  brianp
  69.  * initial rev
  70.  *
  71.  */
  72.  
  73.  
  74. #ifdef PC_HEADER
  75. #include "all.h"
  76. #else
  77. #include <assert.h>
  78. #include <stdlib.h>
  79. #include <string.h>
  80. #include "context.h"
  81. #include "drawpix.h"
  82. #include "feedback.h"
  83. #include "image.h"
  84. #include "macros.h"
  85. #include "pixel.h"
  86. #include "span.h"
  87. #include "stencil.h"
  88. #include "types.h"
  89. #include "zoom.h"
  90. #endif
  91.  
  92.  
  93.  
  94. /* TODO:  apply texture mapping to fragments */
  95.  
  96.  
  97. /*
  98.  * Try to do a fast glDrawPixels.  Conditions include:
  99.  *   not using a display list
  100.  *   simple pixel unpacking
  101.  *   no raster ops
  102.  *   etc....
  103.  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
  104.  */
  105. GLboolean gl_direct_DrawPixels( GLcontext *ctx,
  106.                                 const struct gl_pixelstore_attrib *unpack,
  107.                                 GLsizei width, GLsizei height,
  108.                                 GLenum format, GLenum type,
  109.                                 const GLvoid *pixels )
  110. {
  111.    GLubyte rgb[MAX_WIDTH][3];
  112.    GLubyte rgba[MAX_WIDTH][4];
  113.  
  114.    if (INSIDE_BEGIN_END(ctx)) {
  115.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels" );
  116.       return GL_TRUE;
  117.    }
  118.  
  119.    if (!ctx->Current.RasterPosValid) {
  120.       /* no-op */
  121.       return GL_TRUE;
  122.    }
  123.  
  124.    if (ctx->NewState) {
  125.       gl_update_state(ctx);
  126.    }
  127.  
  128.    /* see if device driver can do the drawpix */
  129.    if (ctx->Driver.DrawPixels) {
  130.       GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  131.       GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  132.       if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
  133.                                     unpack, pixels))
  134.          return GL_TRUE;
  135.    }
  136.  
  137.    if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
  138.        && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
  139.        && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
  140.        && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
  141.        && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
  142.        && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
  143.        && ctx->Pixel.MapColorFlag==0
  144.        && unpack->Alignment==1
  145.        && !unpack->SwapBytes
  146.        && !unpack->LsbFirst) {
  147.  
  148.       GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  149.       GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  150.       GLint drawWidth = width;           /* actual width drawn */
  151.       GLint drawHeight = height;         /* actual height drawn */
  152.       GLint skipPixels = unpack->SkipPixels;
  153.       GLint skipRows = unpack->SkipRows;
  154.       GLint rowLength;
  155.       GLdepth zSpan[MAX_WIDTH];  /* only used when zooming */
  156.       GLint zoomY0;
  157.  
  158.       if (unpack->RowLength > 0)
  159.          rowLength = unpack->RowLength;
  160.       else
  161.          rowLength = width;
  162.  
  163.       /* If we're not using pixel zoom then do all clipping calculations
  164.        * now.  Otherwise, we'll let the gl_write_zoomed_*_span() functions
  165.        * handle the clipping.
  166.        */
  167.       if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  168.          /* horizontal clipping */
  169.          if (destX < ctx->Buffer->Xmin) {
  170.             skipPixels += (ctx->Buffer->Xmin - destX);
  171.             drawWidth  -= (ctx->Buffer->Xmin - destX);
  172.             destX = ctx->Buffer->Xmin;
  173.          }
  174.          if (destX + drawWidth > ctx->Buffer->Xmax)
  175.             drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1);
  176.          if (drawWidth <= 0)
  177.             return GL_TRUE;
  178.  
  179.          /* vertical clipping */
  180.          if (destY < ctx->Buffer->Ymin) {
  181.             skipRows   += (ctx->Buffer->Ymin - destY);
  182.             drawHeight -= (ctx->Buffer->Ymin - destY);
  183.             destY = ctx->Buffer->Ymin;
  184.          }
  185.          if (destY + drawHeight > ctx->Buffer->Ymax)
  186.             drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
  187.          if (drawHeight <= 0)
  188.             return GL_TRUE;
  189.       }
  190.       else {
  191.          /* setup array of fragment Z value to pass to zoom function */
  192.          GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  193.          GLint i;
  194.          assert(drawWidth < MAX_WIDTH);
  195.          for (i=0; i<drawWidth; i++)
  196.             zSpan[i] = z;
  197.  
  198.          /* save Y value of first row */
  199.          zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  200.       }
  201.  
  202.  
  203.       /*
  204.        * Ready to draw!
  205.        * The window region at (destX, destY) of size (drawWidth, drawHeight)
  206.        * will be written to.
  207.        * We'll take pixel data from buffer pointed to by "pixels" but we'll
  208.        * skip "skipRows" rows and skip "skipPixels" pixels/row.
  209.        */
  210.  
  211.       if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
  212.          if (ctx->Visual->RGBAflag) {
  213.             GLubyte *src = (GLubyte *) pixels
  214.                + (skipRows * rowLength + skipPixels) * 4;
  215.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  216.                /* no zooming */
  217.                GLint row;
  218.                for (row=0; row<drawHeight; row++) {
  219.                   (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  220.                                                (void *) src, NULL);
  221.                   src += rowLength * 4;
  222.                   destY++;
  223.                }
  224.             }
  225.             else {
  226.                /* with zooming */
  227.                GLint row;
  228.                for (row=0; row<drawHeight; row++) {
  229.                   gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
  230.                                             zSpan, (void *) src, zoomY0);
  231.                   src += rowLength * 4;
  232.                   destY++;
  233.                }
  234.             }
  235.          }
  236.          return GL_TRUE;
  237.       }
  238.       else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
  239.          if (ctx->Visual->RGBAflag) {
  240.             GLubyte *src = (GLubyte *) pixels
  241.                + (skipRows * rowLength + skipPixels) * 3;
  242.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  243.                GLint row;
  244.                for (row=0; row<drawHeight; row++) {
  245.                   (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  246.                                               (void *) src, NULL);
  247.                   src += rowLength * 3;
  248.                   destY++;
  249.                }
  250.             }
  251.             else {
  252.                /* with zooming */
  253.                GLint row;
  254.                for (row=0; row<drawHeight; row++) {
  255.                   gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
  256.                                            zSpan, (void *) src, zoomY0);
  257.                   src += rowLength * 3;
  258.                   destY++;
  259.                }
  260.             }
  261.          }
  262.          return GL_TRUE;
  263.       }
  264.       else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
  265.          if (ctx->Visual->RGBAflag) {
  266.             GLubyte *src = (GLubyte *) pixels
  267.                + (skipRows * rowLength + skipPixels);
  268.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  269.                /* no zooming */
  270.                GLint row;
  271.                assert(drawWidth < MAX_WIDTH);
  272.                for (row=0; row<drawHeight; row++) {
  273.                   GLint i;
  274.           for (i=0;i<drawWidth;i++) {
  275.                      rgb[i][0] = src[i];
  276.                      rgb[i][1] = src[i];
  277.                      rgb[i][2] = src[i];
  278.           }
  279.                   (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  280.                                               (void *) rgb, NULL);
  281.                   src += rowLength;
  282.                   destY++;
  283.                }
  284.             }
  285.             else {
  286.                /* with zooming */
  287.                GLint row;
  288.                assert(drawWidth < MAX_WIDTH);
  289.                for (row=0; row<drawHeight; row++) {
  290.                   GLint i;
  291.           for (i=0;i<drawWidth;i++) {
  292.                      rgb[i][0] = src[i];
  293.                      rgb[i][1] = src[i];
  294.                      rgb[i][2] = src[i];
  295.           }
  296.                   gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
  297.                                            zSpan, (void *) rgb, zoomY0);
  298.                   src += rowLength;
  299.                   destY++;
  300.                }
  301.             }
  302.          }
  303.          return GL_TRUE;
  304.       }
  305.       else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
  306.          if (ctx->Visual->RGBAflag) {
  307.             GLubyte *src = (GLubyte *) pixels
  308.                + (skipRows * rowLength + skipPixels)*2;
  309.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  310.                /* no zooming */
  311.                GLint row;
  312.                assert(drawWidth < MAX_WIDTH);
  313.                for (row=0; row<drawHeight; row++) {
  314.                   GLint i;
  315.                   GLubyte *ptr = src;
  316.           for (i=0;i<drawWidth;i++) {
  317.                      rgba[i][0] = *ptr;
  318.                      rgba[i][1] = *ptr;
  319.                      rgba[i][2] = *ptr++;
  320.                      rgba[i][3] = *ptr++;
  321.           }
  322.                   (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  323.                                                (void *) rgba, NULL);
  324.                   src += rowLength*2;
  325.                   destY++;
  326.                }
  327.             }
  328.             else {
  329.                /* with zooming */
  330.                GLint row;
  331.                assert(drawWidth < MAX_WIDTH);
  332.                for (row=0; row<drawHeight; row++) {
  333.                   GLubyte *ptr = src;
  334.                   GLint i;
  335.           for (i=0;i<drawWidth;i++) {
  336.                      rgba[i][0] = *ptr;
  337.                      rgba[i][1] = *ptr;
  338.                      rgba[i][2] = *ptr++;
  339.                      rgba[i][3] = *ptr++;
  340.           }
  341.                   gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
  342.                                             zSpan, (void *) rgba, zoomY0);
  343.                   src += rowLength*2;
  344.                   destY++;
  345.                }
  346.             }
  347.          }
  348.          return GL_TRUE;
  349.       }
  350.       else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
  351.          GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
  352.          if (ctx->Visual->RGBAflag) {
  353.             /* convert CI data to RGBA */
  354.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  355.                /* no zooming */
  356.                GLint row;
  357.                for (row=0; row<drawHeight; row++) {
  358.                   assert(drawWidth < MAX_WIDTH);
  359.                   gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
  360.                   (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  361.                                                rgba, NULL);
  362.                   src += rowLength;
  363.                   destY++;
  364.                }
  365.                return GL_TRUE;
  366.             }
  367.             else {
  368.                /* with zooming */
  369.                GLint row;
  370.                for (row=0; row<drawHeight; row++) {
  371.                   assert(drawWidth < MAX_WIDTH);
  372.                   gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
  373.                   gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
  374.                                             zSpan, (void *) rgba, zoomY0);
  375.                   src += rowLength;
  376.                   destY++;
  377.                }
  378.                return GL_TRUE;
  379.             }
  380.          }
  381.          else {
  382.             /* write CI data to CI frame buffer */
  383.             GLint row;
  384.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  385.                /* no zooming */
  386.                for (row=0; row<drawHeight; row++) {
  387.                   (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
  388.                                               src, NULL);
  389.                   src += rowLength;
  390.                   destY++;
  391.                }
  392.                return GL_TRUE;
  393.             }
  394.             else {
  395.                /* with zooming */
  396.                return GL_FALSE;
  397.             }
  398.          }
  399.       }
  400.       else {
  401.          /* can't handle this pixel format and/or data type here */
  402.          return GL_FALSE;
  403.       }
  404.    }
  405.    else {
  406.       /* can't do direct render, have to use slow path */
  407.       return GL_FALSE;
  408.    }
  409. }
  410.  
  411.  
  412.  
  413. /*
  414.  * Do glDrawPixels of index pixels.
  415.  */
  416. static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
  417.                                const struct gl_image *image )
  418. {
  419.    GLint width, height, widthInBytes;
  420.    const GLint desty = y;
  421.    GLint i, j;
  422.    GLdepth zspan[MAX_WIDTH];
  423.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  424.  
  425.    assert(image);
  426.    assert(image->Format == GL_COLOR_INDEX);
  427.  
  428.    width = image->Width;
  429.    height = image->Height;
  430.    if (image->Type == GL_BITMAP)
  431.       widthInBytes = (width + 7) / 8;
  432.    else
  433.       widthInBytes = width;
  434.  
  435.    /* Fragment depth values */
  436.    if (ctx->Depth.Test) {
  437.       GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  438.       for (i=0;i<width;i++) {
  439.      zspan[i] = zval;
  440.       }
  441.    }
  442.  
  443.    /* process the image row by row */
  444.    for (i=0;i<height;i++,y++) {
  445.       GLuint ispan[MAX_WIDTH];
  446.  
  447.       /* convert to uints */
  448.       switch (image->Type) {
  449.      case GL_UNSIGNED_BYTE:
  450.         {
  451.            GLubyte *src = (GLubyte *) image->Data + i * width;
  452.            for (j=0;j<width;j++) {
  453.           ispan[j] = (GLuint) *src++;
  454.            }
  455.         }
  456.         break;
  457.      case GL_FLOAT:
  458.         {
  459.            GLfloat *src = (GLfloat *) image->Data + i * width;
  460.            for (j=0;j<width;j++) {
  461.           ispan[j] = (GLuint) (GLint) *src++;
  462.            }
  463.         }
  464.         break;
  465.          case GL_BITMAP:
  466.             {
  467.            GLubyte *src = (GLubyte *) image->Data + i * widthInBytes;
  468.            for (j=0;j<width;j++) {
  469.           ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
  470.            }
  471.             }
  472.             break;
  473.      default:
  474.         gl_problem( ctx, "draw_index_pixels type" );
  475.             return;
  476.       }
  477.  
  478.       /* apply shift and offset */
  479.       if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
  480.          gl_shift_and_offset_ci( ctx, width, ispan );
  481.       }
  482.  
  483.       if (ctx->Visual->RGBAflag) {
  484.      /* Convert index to RGBA and write to frame buffer */
  485.      GLubyte rgba[MAX_WIDTH][4];
  486.          gl_map_ci_to_rgba( ctx, width, ispan, rgba );
  487.          if (zoom) {
  488.             gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, rgba, desty );
  489.          }
  490.          else {
  491.             gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
  492.          }
  493.       }
  494.       else {
  495.      /* optionally apply index map then write to frame buffer */
  496.      if (ctx->Pixel.MapColorFlag) {
  497.             gl_map_ci(ctx, width, ispan);
  498.      }
  499.          if (zoom) {
  500.             gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
  501.          }
  502.          else {
  503.             gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
  504.          }
  505.       }
  506.    }
  507.  
  508. }
  509.  
  510.  
  511.  
  512. /*
  513.  * Do glDrawPixels of stencil image.  The image datatype may either
  514.  * be GLubyte or GLbitmap.
  515.  */
  516. static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
  517.                                  const struct gl_image *image )
  518. {
  519.    GLint widthInBytes, width, height;
  520.    const GLint desty = y;
  521.    GLint i;
  522.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  523.  
  524.    assert(image);
  525.    assert(image->Format == GL_STENCIL_INDEX);
  526.    assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
  527.  
  528.    if (image->Type == GL_UNSIGNED_BYTE)
  529.       widthInBytes = image->Width;
  530.    else
  531.       widthInBytes = (image->Width + 7) / 8;
  532.    width = image->Width;
  533.    height = image->Height;
  534.  
  535.    /* process the image row by row */
  536.    for (i=0;i<height;i++,y++) {
  537.       GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
  538.       GLstencil *stencilValues;
  539.       GLstencil stencilCopy[MAX_WIDTH];
  540.  
  541.       if (image->Type == GL_BITMAP) {
  542.          /* convert bitmap data to GLubyte (0 or 1) data */
  543.          GLint j;
  544.          for (j = 0; j < width; j++) {
  545.             stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
  546.          }
  547.          src = stencilCopy;
  548.       }
  549.  
  550.       if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
  551.           || ctx->Pixel.MapStencilFlag) {
  552.  
  553.          /* make copy of stencil values */
  554.          if (src != stencilCopy)
  555.             MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
  556.  
  557.          /* apply shift and offset */
  558.          if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
  559.             gl_shift_and_offset_stencil( ctx, width, stencilCopy );
  560.          }
  561.  
  562.          /* mapping */
  563.          if (ctx->Pixel.MapStencilFlag) {
  564.             gl_map_stencil( ctx, width, stencilCopy );
  565.          }
  566.  
  567.          stencilValues = stencilCopy;
  568.       }
  569.       else {
  570.          /* use stencil values in-place */
  571.          stencilValues = src;
  572.       }
  573.  
  574.       /* write stencil values to stencil buffer */
  575.       if (zoom) {
  576.          gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
  577.                                        stencilValues, desty );
  578.       }
  579.       else {
  580.          gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
  581.       }
  582.    }
  583. }
  584.  
  585.  
  586.  
  587. /*
  588.  * Do a glDrawPixels of depth values.
  589.  */
  590. static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
  591.                                const struct gl_image *image )
  592. {
  593.    GLint width, height;
  594.    const GLint desty = y;
  595.    GLubyte rgba[MAX_WIDTH][4];
  596.    GLuint ispan[MAX_WIDTH];
  597.    const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
  598.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  599.  
  600.    assert(image);
  601.    assert(image->Format == GL_DEPTH_COMPONENT);
  602.  
  603.    width = image->Width;
  604.    height = image->Height;
  605.  
  606.    /* Color or index */
  607.    if (ctx->Visual->RGBAflag) {
  608.       GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
  609.       GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
  610.       GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
  611.       GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
  612.       GLint i;
  613.       for (i=0; i<width; i++) {
  614.          rgba[i][RCOMP] = r;
  615.          rgba[i][GCOMP] = g;
  616.          rgba[i][BCOMP] = b;
  617.          rgba[i][ACOMP] = a;
  618.       }
  619.    }
  620.    else {
  621.       GLint i;
  622.       for (i=0;i<width;i++) {
  623.      ispan[i] = ctx->Current.RasterIndex;
  624.       }
  625.    }
  626.  
  627.    if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
  628.        && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
  629.       /* Special case: directly write 16-bit depth values */
  630.       GLint j;
  631.       for (j=0;j<height;j++,y++) {
  632.          GLdepth *zptr = (GLdepth *) image->Data + j * width;
  633.          gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
  634.       }
  635.    }
  636.    else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
  637.        && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
  638.       /* Special case: directly write 32-bit depth values */
  639.       GLint i, j;
  640.       /* Compute shift value to scale 32-bit uints down to depth values. */
  641.       GLuint shift = 0;
  642.       GLuint max = MAX_DEPTH;
  643.       while ((max&0x80000000)==0) {
  644.          max = max << 1;
  645.          shift++;
  646.       }
  647.       for (j=0;j<height;j++,y++) {
  648.          GLdepth zspan[MAX_WIDTH];
  649.          GLuint *zptr = (GLuint *) image->Data + j * width;
  650.          for (i=0;i<width;i++) {
  651.             zspan[i] = zptr[i] >> shift;
  652.          }
  653.          gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
  654.       }
  655.    }
  656.    else {
  657.       /* General case (slower) */
  658.       GLint i, j;
  659.  
  660.       /* process image row by row */
  661.       for (i=0;i<height;i++,y++) {
  662.          GLfloat depth[MAX_WIDTH];
  663.          GLdepth zspan[MAX_WIDTH];
  664.  
  665.          switch (image->Type) {
  666.             case GL_UNSIGNED_SHORT:
  667.                {
  668.                   GLushort *src = (GLushort *) image->Data + i * width;
  669.                   for (j=0;j<width;j++) {
  670.                      depth[j] = USHORT_TO_FLOAT( *src++ );
  671.                   }
  672.                }
  673.                break;
  674.             case GL_UNSIGNED_INT:
  675.                {
  676.                   GLuint *src = (GLuint *) image->Data + i * width;
  677.                   for (j=0;j<width;j++) {
  678.                      depth[j] = UINT_TO_FLOAT( *src++ );
  679.                   }
  680.                }
  681.                break;
  682.             case GL_FLOAT:
  683.                {
  684.                   GLfloat *src = (GLfloat *) image->Data + i * width;
  685.                   for (j=0;j<width;j++) {
  686.                      depth[j] = *src++;
  687.                   }
  688.                }
  689.                break;
  690.             default:
  691.                gl_problem(ctx, "Bad type in draw_depth_pixels");
  692.                return;
  693.          }
  694.  
  695.          /* apply depth scale and bias */
  696.          if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
  697.             for (j=0;j<width;j++) {
  698.                depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  699.             }
  700.          }
  701.  
  702.          /* clamp depth values to [0,1] and convert from floats to integers */
  703.          for (j=0;j<width;j++) {
  704.             zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
  705.          }
  706.  
  707.          if (ctx->Visual->RGBAflag) {
  708.             if (zoom) {
  709.                gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
  710.                                           rgba, desty );
  711.             }
  712.             else {
  713.                gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
  714.             }
  715.          }
  716.          else {
  717.             if (zoom) {
  718.                gl_write_zoomed_index_span( ctx, width, x, y, zspan,
  719.                                            ispan, GL_BITMAP );
  720.             }
  721.             else {
  722.                gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
  723.             }
  724.          }
  725.  
  726.       }
  727.    }
  728. }
  729.  
  730.  
  731.  
  732. /* Simple unpacking parameters: */
  733. static struct gl_pixelstore_attrib NoUnpack = {
  734.    1,            /* Alignment */
  735.    0,            /* RowLength */
  736.    0,            /* SkipPixels */
  737.    0,            /* SkipRows */
  738.    0,            /* ImageHeight */
  739.    0,            /* SkipImages */
  740.    GL_FALSE,     /* SwapBytes */
  741.    GL_FALSE      /* LsbFirst */
  742. };
  743.  
  744.  
  745. /*
  746.  * Do glDrawPixels of RGBA pixels.
  747.  */
  748. static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
  749.                               const struct gl_image *image )
  750. {
  751.    GLint width, height;
  752.    GLint i, j;
  753.    const GLint desty = y;
  754.    GLdepth zspan[MAX_WIDTH];
  755.    GLboolean quickDraw;
  756.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  757.  
  758.    assert(image);
  759.  
  760.    /* Try an optimized glDrawPixels first */
  761.    if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
  762.                             image->Format, image->Type, image->Data ))
  763.       return;
  764.  
  765.    width = image->Width;
  766.    height = image->Height;
  767.  
  768.    /* Fragment depth values */
  769.    if (ctx->Depth.Test) {
  770.       /* fill in array of z values */
  771.       GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  772.       for (i=0;i<width;i++) {
  773.      zspan[i] = z;
  774.       }
  775.    }
  776.  
  777.    if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
  778.        && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
  779.       quickDraw = GL_TRUE;
  780.    }
  781.    else {
  782.       quickDraw = GL_FALSE;
  783.    }
  784.  
  785.    {
  786.       /* General solution */
  787.       GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
  788.       GLuint components;
  789.       DEFARRAY(GLfloat, rf, MAX_WIDTH);
  790.       DEFARRAY(GLfloat, gf, MAX_WIDTH);
  791.       DEFARRAY(GLfloat, bf, MAX_WIDTH);
  792.       DEFARRAY(GLfloat, af, MAX_WIDTH);
  793.       GLubyte rgba[MAX_WIDTH][4];
  794.  
  795.       r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
  796.       switch (image->Format) {
  797.      case GL_RED:
  798.         r_flag = GL_TRUE;
  799.         components = 1;
  800.         break;
  801.      case GL_GREEN:
  802.         g_flag = GL_TRUE;
  803.         components = 1;
  804.         break;
  805.      case GL_BLUE:
  806.         b_flag = GL_TRUE;
  807.         components = 1;
  808.         break;
  809.      case GL_ALPHA:
  810.         a_flag = GL_TRUE;
  811.         components = 1;
  812.         break;
  813.      case GL_RGB:
  814.         r_flag = g_flag = b_flag = GL_TRUE;
  815.         components = 3;
  816.         break;
  817.      case GL_LUMINANCE:
  818.         l_flag = GL_TRUE;
  819.         components = 1;
  820.         break;
  821.      case GL_LUMINANCE_ALPHA:
  822.         l_flag = a_flag = GL_TRUE;
  823.         components = 2;
  824.         break;
  825.      case GL_RGBA:
  826.         r_flag = g_flag = b_flag = a_flag = GL_TRUE;
  827.         components = 4;
  828.         break;
  829.          default:
  830.             gl_problem(ctx, "Bad type in draw_rgba_pixels");
  831.             goto cleanup;
  832.       }
  833.  
  834.       /* process the image row by row */
  835.       for (i=0;i<height;i++,y++) {
  836.      /* convert to floats */
  837.      switch (image->Type) {
  838.         case GL_UNSIGNED_BYTE:
  839.            {
  840.           GLubyte *src = (GLubyte *) image->Data + i * width * components;
  841.           for (j=0;j<width;j++) {
  842.              if (l_flag) {
  843.             rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
  844.              }
  845.              else {
  846.             rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
  847.             gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
  848.             bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
  849.              }
  850.              af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
  851.           }
  852.            }
  853.            break;
  854.         case GL_FLOAT:
  855.            {
  856.           GLfloat *src = (GLfloat *) image->Data + i * width * components;
  857.           for (j=0;j<width;j++) {
  858.              if (l_flag) {
  859.             rf[j] = gf[j] = bf[j] = *src++;
  860.              }
  861.              else {
  862.             rf[j] = r_flag ? *src++ : 0.0;
  863.             gf[j] = g_flag ? *src++ : 0.0;
  864.             bf[j] = b_flag ? *src++ : 0.0;
  865.              }
  866.              af[j] = a_flag ? *src++ : 1.0;
  867.           }
  868.            }
  869.            break;
  870.         default:
  871.            gl_problem( ctx, "draw_rgba_pixels type" );
  872.                goto cleanup;
  873.      }
  874.  
  875.      /* apply scale and bias */
  876.      if (ctx->Pixel.ScaleOrBiasRGBA) {
  877.             gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
  878.      }
  879.  
  880.      /* apply pixel mappings */
  881.      if (ctx->Pixel.MapColorFlag) {
  882.             gl_map_color(ctx, width, rf, gf, bf, af);
  883.      }
  884.  
  885.      /* convert to integers */
  886.      for (j=0;j<width;j++) {
  887.         rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
  888.         rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
  889.         rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
  890.         rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
  891.      }
  892.  
  893.      /* write to frame buffer */
  894.          if (quickDraw) {
  895.             (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, rgba, NULL);
  896.          }
  897.          else if (zoom) {
  898.             gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, rgba, desty );
  899.          }
  900.          else {
  901.             gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
  902.          }
  903.       }
  904. cleanup:
  905.       UNDEFARRAY(rf);
  906.       UNDEFARRAY(gf);
  907.       UNDEFARRAY(bf);
  908.       UNDEFARRAY(af);
  909.    }
  910. }
  911.  
  912.  
  913.  
  914. /*
  915.  * Execute glDrawPixels
  916.  */
  917. void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
  918. {
  919.    if (INSIDE_BEGIN_END(ctx)) {
  920.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels" );
  921.       return;
  922.    }
  923.  
  924.    if (gl_image_error_test( ctx, image, "glDrawPixels" ))
  925.       return;
  926.  
  927.    if (ctx->RenderMode==GL_RENDER) {
  928.       GLint x, y;
  929.       if (!ctx->Current.RasterPosValid) {
  930.      return;
  931.       }
  932.  
  933.       x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  934.       y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  935.  
  936.       switch (image->Format) {
  937.      case GL_COLOR_INDEX:
  938.             draw_index_pixels( ctx, x, y, image );
  939.         break;
  940.      case GL_STENCIL_INDEX:
  941.         draw_stencil_pixels( ctx, x, y, image );
  942.         break;
  943.      case GL_DEPTH_COMPONENT:
  944.         draw_depth_pixels( ctx, x, y, image );
  945.         break;
  946.      case GL_RED:
  947.      case GL_GREEN:
  948.      case GL_BLUE:
  949.      case GL_ALPHA:
  950.      case GL_RGB:
  951.      case GL_LUMINANCE:
  952.      case GL_LUMINANCE_ALPHA:
  953.      case GL_RGBA:
  954.             draw_rgba_pixels( ctx, x, y, image );
  955.         break;
  956.      default:
  957.         gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
  958.             return;
  959.       }
  960.    }
  961.    else if (ctx->RenderMode==GL_FEEDBACK) {
  962.       if (ctx->Current.RasterPosValid) {
  963.          GLfloat color[4], texcoord[4], invq;
  964.          color[0] = (GLfloat) ctx->Current.ByteColor[0] / 255.0;
  965.          color[1] = (GLfloat) ctx->Current.ByteColor[1] / 255.0;
  966.          color[2] = (GLfloat) ctx->Current.ByteColor[2] / 255.0;
  967.          color[3] = (GLfloat) ctx->Current.ByteColor[3] / 255.0;
  968.          invq = 1.0F / ctx->Current.TexCoord[3];
  969.          texcoord[0] = ctx->Current.TexCoord[0] * invq;
  970.          texcoord[1] = ctx->Current.TexCoord[1] * invq;
  971.          texcoord[2] = ctx->Current.TexCoord[2] * invq;
  972.          texcoord[3] = ctx->Current.TexCoord[3];
  973.          FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
  974.          gl_feedback_vertex( ctx,
  975.                              ctx->Current.RasterPos[0],
  976.                              ctx->Current.RasterPos[1],
  977.                              ctx->Current.RasterPos[2],
  978.                              ctx->Current.RasterPos[3],
  979.                              color, ctx->Current.Index, texcoord );
  980.       }
  981.    }
  982.    else if (ctx->RenderMode==GL_SELECT) {
  983.       if (ctx->Current.RasterPosValid) {
  984.          gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  985.       }
  986.    }
  987. }
  988.  
  989.